using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace DungeonOfDespair
{
    public enum EntityDirection
    {
        Down,
        Left,
        Right,
        Up
    }

    public class Character
        : Entity
    {
        private Sprite m_sprite;
        private int m_iMoveX;
        private int m_iMoveY;
        private EntityDirection m_entityDirection;
        private int m_iSpeed;
        private bool m_bAutomaticDirection;
        private int m_iHealth;
        private int m_iFrame;
        private int m_iFrameWait;
        private RectangleF[][] m_rectFrames;

        public Character(Image imageSprite)
        {
            m_sprite = new Sprite(imageSprite);
            m_iPositionX = 0;
            m_iPositionY = 0;
            m_iMoveX = 0;
            m_iMoveY = 0;
            m_entityDirection = EntityDirection.Down;
            m_iSpeed = 4;
            m_iFrame = 0;
            m_iFrameWait = 0;

            int iFrameWidth = imageSprite.Width / 4;
            int iFrameHeight = imageSprite.Height / 4;
            m_rectFrames = new RectangleF[4][];
            for (int iIndex = 0; iIndex < 4; iIndex++)
            {
                m_rectFrames[iIndex] = new RectangleF[4];
                for (int iIndex2 = 0; iIndex2 < 4; iIndex2++)
                    m_rectFrames[iIndex][iIndex2]
                        = new RectangleF(
                            iFrameWidth * iIndex2,
                            iFrameHeight * iIndex,
                            iFrameWidth, iFrameHeight);
            }

            Bounds = new RectangleF(-iFrameWidth / 2, -iFrameHeight / 2, iFrameWidth, iFrameHeight / 2);
        }

        public override void Update()
        {
            base.Update();

            if (m_iMoveX > 0)
            {
                int iDelta = Math.Min(m_iMoveX, m_iSpeed);
                m_iPositionX += iDelta;
                m_iMoveX -= iDelta;
            }
            if (m_iMoveX < 0)
            {
                int iDelta = Math.Max(m_iMoveX, -m_iSpeed);
                m_iPositionX += iDelta;
                m_iMoveX -= iDelta;
            }
            if (m_iMoveY > 0)
            {
                int iDelta = Math.Min(m_iMoveY, m_iSpeed);
                m_iPositionY += iDelta;
                m_iMoveY -= iDelta;
            }
            if (m_iMoveY < 0)
            {
                int iDelta = Math.Max(m_iMoveY, -m_iSpeed);
                m_iPositionY += iDelta;
                m_iMoveY -= iDelta;
            }
            if (m_iMoveX != 0 || m_iMoveY != 0)
            {
                m_iFrameWait = (m_iFrameWait + 1) % 3;
                if (m_iFrameWait == 0)
                    m_iFrame = (m_iFrame + 1) % 4;
            }
            else
                m_iFrame = 0;

            if (!m_bAutomaticDirection) return;
            if (m_iMoveX == 0)
            {  
                if (m_iMoveY > 0)
                    m_entityDirection = EntityDirection.Down;
                else if (m_iMoveY < 0)
                    m_entityDirection = EntityDirection.Up;
            }
            else if (m_iMoveX > 0)
                m_entityDirection = EntityDirection.Right;
            else if (m_iMoveX < 0)
                m_entityDirection = EntityDirection.Left;
        }

        public override void Draw(Graphics graphics)
        {
            m_sprite.X = m_iPositionX;
            m_sprite.Y = m_iPositionY;

            m_sprite.ClipBounds = m_rectFrames[(int) m_entityDirection][m_iFrame];
            m_sprite.CentreHotspot(ClipPosition.Bottom);
            m_sprite.Draw(graphics);
        }

        public void Move(int iDeltaX, int iDeltaY)
        {
            m_iMoveX = iDeltaX;
            m_iMoveY = iDeltaY;
        }

        public void MoveTo(int iTargetX, int iTargetY)
        {
            m_iMoveX = iTargetX - m_iPositionX;
            m_iMoveY = iTargetY - m_iPositionY;
        }

        public EntityDirection Direction
        {
            get { return m_entityDirection; }
            set { m_entityDirection = value; }
        }

        public int Speed
        {
            get { return m_iSpeed; }
            set { m_iSpeed = Math.Max(1, value); }
        }

        public bool AutomaticDirection
        {
            get { return m_bAutomaticDirection; }
            set { m_bAutomaticDirection = value; }
        }

        public bool Moving
        {
            get { return m_iMoveX != 0 || m_iMoveY != 0; }
        }

        public int Health
        {
            get { return m_iHealth; }
            set { m_iHealth = value; }
        }
    }
}
